package org.batatasframework.support.charts;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class ResultDataReader {
	
	private Map<String, Number> maps = new LinkedHashMap<>();
	
	private final ChartResultParser parser;
	
	public ResultDataReader(ChartResultParser parser){
		this.parser = parser;
	}
	
	public ResultDataReader(){
		this(ChartResultParser.numberParser());
	}
	
	/**
	 * <pre>
	 * 把0值去掉
	 * 
	 * 把结果集里的0值，包括这一项的名称都去掉。
	 * </pre>
	 */
	public ResultDataReader filteZore(){
		List<String> needRemove = new ArrayList<>();
		for(Entry<String, Number> en : maps.entrySet()){
			if(en.getValue().longValue() == 0){
				needRemove.add(en.getKey());
//				maps.remove(en.getKey());
			}
		}
		for(String rkey : needRemove){
			maps.remove(rkey);
		}
		return this;
	}
	
	public String[] getLables(){
		return maps.keySet().toArray(new String[maps.size()]);
	}
	
	public Object[] getData(){
		if(null == parser) return maps.values().toArray();
		return parser.parse(maps);
	}

//	private boolean checkIn(String value, ChartValueMatcher...limits){
//		for(ChartValueMatcher li : limits){
//			if(li.match(value)) return true;
//		}
//		return false;
//	}
	
	public ResultDataReader read(List<Object> items){
		return this;
	}
	
//	private class CountResultReader extends ResultDataReader{
//		
//		protected CountResultReader(ChartResultParser parser){ 
//			super(parser);
//		}
//		
//		protected CountResultReader(){ }
//		
//	}
//	
//	private class SumResultReader extends ResultDataReader{
//		
//		protected SumResultReader(ChartResultParser parser){ 
//			super(parser);
//		}
//		
//		protected SumResultReader(){ }
//		
//	}
	
	/**
	 * <pre>
	 * 把读取的内容限制在指定的字符串内；
	 * 如果出现未定义的字符串的，则忽略
	 * </pre>
	 */
	//public void sumNumberLimit(List<Object> items, String...limits){
	public void sumNumberLimit(List<Object> items, ChartValueMatcher...limits){
		sumNumberLimit(items, 0, 1, limits);
	}
	
	/**
	 * <pre>
	 * 处理数据库存储的是选择项的下标的情况；根据下标选择的情况来统计对应的项；
	 * 
	 * 注意区分多选项和单选项的问题；
	 * 
	 * 如果单选，则对应的下标值需要"+1"，因为0值为没有选择，不是选择第一个的情况
	 * </pre>
	 */
	public void sumNumberOption(boolean multi, List<Object> items, String...options){
		sumNumberOption(multi, items, 0, 1, options);
	}
	
	/**
	 * <pre>
	 * 处理数据库存储的是选择项的下标的情况；根据下标选择的情况来统计对应的项；
	 * 
	 * 注意区分多选项和单选项的问题；
	 * 
	 * 如果单选，则对应的下标值不需要"+1"，
	 * </pre>
	 */
	public void sumNumberOption2(boolean multi, List<Object> items, String...options){
		sumNumberOption2(multi, items, 0, 1, options);
	}
	
	/**
	 * <pre>
	 * 这是最普通的情况，返回的结果里，直接第一个字段为label，
	 * 第二个字段为统计数据的值，并且已经是统计好的情况
	 * 
	 * 如：查询语句为 select x.name,sum(x.value) ... group by x.name 的查询语句
	 * </pre>
	 */
	public void sumNumber(List<Object> items){
		sumNumber(items, 0, 1);
	}
	
	/**
	 * <pre>
	 * 这里处理的是：
	 * names = {"c0", "c1", "c2"}
	 * 
	 * values = [
	 * 	[2,3,4]
	 * 	[4,5,6]
	 * 	[3,2,4]
	 * 	[4,5,6]
	 * ]
	 * </pre>
	 */
	public void sumNumber(List<Object> items, String...names){
		sumNumber(items, 0, names);
	}
	
//	public void sumNumberFields(List<Object> items, String...fields){
//		sumNumberFields(items, 0, fields);
//	}
	
	public static class ResultDataArgument{
		protected int offset;
		protected String[] names;
	}
	
	public void sumNumber(List<Object> items, int offset, String...names){
		Number[] data = new Number[names.length];
		Arrays.fill(data, 0L);
		
		for(Object obj : items){
			Object[] os = (Object[])obj;
			for(int i = 0; i < data.length; i++){
				data[i] = parser.add(data[i], os, offset + i);
			}
		}
		
		for(int i = 0; i < names.length; i++){
			String nam = names[i];
			
			Number old = maps.get(nam);
			if(null == old){
				maps.put(nam, data[i]);
			}else{
				maps.put(nam, parser.add(old, data[i]));
			}
		}
	}
	
	//public void sumNumberLimit(List<Object> items, int nameIndex, int valueIndex, String...limits){
	public void sumNumberLimit(List<Object> items, int nameIndex, int valueIndex, ChartValueMatcher...limits){

		initMap(limits);

		//TODO 这里判断的时候，值与名字不一定相同的，所以不能直接使用字符串进行判断
		for(Object it : items){
			Object[] vs = (Object[])it;
			if(null == vs[nameIndex]) continue;
			
			String nam = vs[nameIndex].toString();
			for(ChartValueMatcher li : limits){
				if(li.match(nam)){

					Number val = maps.get(li.getName());
					val = parser.add(val, vs, valueIndex);
					maps.put(li.getName(), val);
				}
			}
//			
//			if(checkIn(nam, limits)){
//				Number val = maps.get(nam);
//				val = parser.add(val, vs, valueIndex);
//				maps.put(nam, val);
//			}
		}
	}

	private void initMap(String... labels) {
		if(maps.isEmpty()){
			for(String li : labels){
				maps.put(li, 0L);
			}
		}
	}
	
	public void sumNumberOption(boolean multi, List<Object> items, int optionIndex, int valueIndex, String...options){

		initMap(options);
		
		for(Object it : items){
			Object[] vs = (Object[])it;
			if(null == vs[optionIndex])continue;
			
			int oi = ((Number)vs[optionIndex]).intValue();
			Number lval = ((Number)vs[valueIndex]);
			if(multi){
				for(int i = 0; i < options.length; i++){
					if((oi & (1 << i)) > 0){
						//选中了某个项的情况
						String optName = options[i];
						Number val = maps.get(optName);
						maps.put(optName, parser.add(lval, val));
					}
				}
			}else{
				oi -= 1;
				if(0 <= oi && oi < options.length){
					//选中了某个项的情况
					String optName = options[oi];
					Number val = maps.get(optName);
					maps.put(optName, parser.add(lval, val));
				}
			}
		}
	}
	/**
	 *  数据库对应下标不需要加1
	 * @param multi
	 * @param items
	 * @param optionIndex
	 * @param valueIndex
	 * @param options
	 */
	public void sumNumberOption2(boolean multi, List<Object> items, int optionIndex, int valueIndex, String...options){

		initMap(options);
		
		for(Object it : items){
			Object[] vs = (Object[])it;
			if(null == vs[optionIndex])continue;
			
			int oi = ((Number)vs[optionIndex]).intValue();
			Number lval = ((Number)vs[valueIndex]);
			if(multi){
				for(int i = 0; i < options.length; i++){
					if((oi & (1 << i)) > 0){
						//选中了某个项的情况
						String optName = options[i];
						Number val = maps.get(optName);
						maps.put(optName, parser.add(lval, val));
					}
				}
			}else{
				if(0 <= oi && oi < options.length){
					//选中了某个项的情况
					String optName = options[oi];
					Number val = maps.get(optName);
					maps.put(optName, parser.add(lval, val));
				}
			}
		}
	}
	/** 参考：{@link #sumNumber(List)} */
	public void sumNumber(List<Object> items, int nameIndex, int valueIndex){

		for(Object it : items){
			Object[] vs = (Object[])it;
			if(null == vs[nameIndex]) continue;
			
			String nam = vs[nameIndex].toString();
			Number val = maps.get(nam);
			if(null != val){
				val = parser.add(val, vs, valueIndex);
			}else{
				val = ((Number)vs[valueIndex]);
			}
			maps.put(nam, val);
		}
	}
	
//	public void sumNumberFields(List<Object> items, int offset, String...fields){
//		Number[] data = new Number[fields.length];
//		Arrays.fill(data, 0L);
//		
//		for(Object it : items){
//			Object[] vs = (Object[])it;
//			for(int i = 0; i < fields.length; i++){
//				data[i] = parser.add(data[i], vs, i + offset);
//			}
//		}
//		
//		for(int i = 0; i < fields.length; i++){
//			maps.put(fields[i], data[i]);
//		}
//	}
	
	/**
	 * <pre>
	 * 查询出来的只有一个名字，这里是统计这个名字出现的次数
	 * </pre>
	 */
	public void count(List<Object> items){
		count(items, 0);
	}
	
	public void count(List<Object> items, ChartValueMatcher... matchers){
		count(items, 0, matchers);
	}
	
	/** 参考：{@link #count(List)} */
	public void count(List<Object> items, int nameIndex){
		for(Object it : items){

			Object val = singleValue(it, nameIndex);
			
			if(null == val) continue;
			
			String nam = val.toString();
			Number count = maps.get(nam);
			if(null == count){
				count = 1;
			}else{
				count = count.longValue() + 1;
			}
			maps.put(nam, count);
		}
	}
	
	private void initMap(ChartValueMatcher... matchers){
		if(maps.isEmpty()){
			/* 处理有顺序的 */
			for(ChartValueMatcher matcher : matchers){
				maps.put(matcher.getName(), 0L);
			}
		}
	}
	
	public void count(List<Object> items, int nameIndex, ChartValueMatcher... matchers){
		initMap(matchers);
		
		for(Object it : items){
			
			Object val = singleValue(it, nameIndex);
			
			if(null == val) continue;
			for(ChartValueMatcher matcher : matchers){
				if(matcher.match(val)){
					String nam = matcher.getName();
					Number count = maps.get(nam);
					count = count.longValue() + 1;
					maps.put(nam, count);
					
					break;
				}
			}
		}
	}

	private Object singleValue(Object values, int index) {
		Object val;
		if(values instanceof Object[]){
			val = ((Object[])values)[index];
		}else{
			val = values;
		}
		return val;
	}
}
